Skip to content

Provision on first prompt — mid-session installs never fired SessionStart#26

Merged
nickroci merged 2 commits into
mainfrom
fix/provision-on-first-prompt
Jun 10, 2026
Merged

Provision on first prompt — mid-session installs never fired SessionStart#26
nickroci merged 2 commits into
mainfrom
fix/provision-on-first-prompt

Conversation

@nickroci

@nickroci nickroci commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Installing the plugin mid-session (/plugin install + /reload-plugins) loaded skills/commands/MCP but never provisioned the runtime: ensure-ultan.sh was wired only to SessionStart, which /reload-plugins doesn't fire. The setup looked alive while capturing nothing until the next fresh session.

Fix — provisioning now fires at the earliest of three triggers, all funneled through the installer's atomic lock so they never race:

  1. MCP server start (right after install/reload — the plugin spec has no install-time script, so this is the earliest the plugin gets to run; plugin.json passes CLAUDE_PLUGIN_ROOT/CLAUDE_PLUGIN_DATA into the server env)
  2. SessionStart (fresh-session path, unchanged)
  3. First prompt (the UserPromptSubmit hook falls back to the provisioner when the binary is missing)

README quick-start and the wrapper's not-provisioned message updated to match.

🤖 Generated with Claude Code

nickroci and others added 2 commits June 10, 2026 17:52
…SessionStart

Installing mid-session left the plugin looking alive (skills/commands/MCP
hot-load) while silently capturing nothing: provisioning was wired only to
SessionStart, which /reload-plugins does not fire, so ensure-ultan.sh never
ran and every per-turn hook no-op'd on the missing binary — until the next
fresh session.

The UserPromptSubmit hook now falls back to the provisioner when the binary
is absent: first prompt after a mid-session install kicks off the background
install (instant return, atomic-lock idempotent — repeat prompts exit on the
lock). SessionStart wiring is unchanged for the fresh-session path.

README quick-start now tells the truth about /reload-plugins, and the
bin/ultan wrapper's not-provisioned message says "send any message" instead
of "start a new session".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…in practice

The plugin spec has no install-time script, but Claude Code starts the
plugin's MCP server right after /plugin install + /reload-plugins — the
earliest code the plugin gets to run. `ultan mcp` now fires the background
installer when the runtime is missing, with plugin.json passing
CLAUDE_PLUGIN_ROOT/CLAUDE_PLUGIN_DATA into its env (documented mcpServers
expansion); missing vars degrade to a no-op.

Provisioning now starts at the earliest of: MCP server start (~install
time), SessionStart (fresh session), or first prompt (mid-session install)
— all funneled through ensure-ultan.sh's atomic lock, so concurrent
triggers collapse into one install.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nickroci nickroci merged commit 0f44544 into main Jun 10, 2026
6 checks passed
@nickroci nickroci deleted the fix/provision-on-first-prompt branch June 10, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant